package org.suspi.skarabee.monitoring;

import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Random;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import com.merge.skarabee.R;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.TextView;

/**
 * A simple {@link android.support.v4.app.Fragment} subclass. Activities that
 * contain this fragment must implement the
 * {@link ChartFragment.OnFragmentInteractionListener} interface to handle
 * interaction events. Use the {@link ChartFragment#newInstance} factory method
 * to create an instance of this fragment.
 * 
 */


public class ChartFragment extends Fragment implements OnClickListener{

	private static Random random = new Random();


	private static TimeSeries timeSeriesa1;
	private static TimeSeries timeSeriesa2;
	private static TimeSeries timeSeriesa3;
	private static TimeSeries timeSeriesa4;
	private static TimeSeries timeSeriesb1;
	private static TimeSeries timeSeriesb2;
	private static TimeSeries timeSeriesb3;
	private static TimeSeries timeSeriesb4;

	private static XYSeriesRenderer rendererSeriesa1;
	private static XYSeriesRenderer rendererSeriesa2;
	private static XYSeriesRenderer rendererSeriesa3;
	private static XYSeriesRenderer rendererSeriesa4;
	private static XYSeriesRenderer rendererSeriesb1;
	private static XYSeriesRenderer rendererSeriesb2;
	private static XYSeriesRenderer rendererSeriesb3;
	private static XYSeriesRenderer rendererSeriesb4;

	private static ArrayList<XYSeriesRenderer> seriesRendererList;
	private static ArrayList<TimeSeries> seriesList;

	private static XYMultipleSeriesDataset datasetA;
	private static XYMultipleSeriesDataset datasetB;
	private static XYMultipleSeriesRenderer rendererA;
	private static XYMultipleSeriesRenderer rendererB;

	private static GraphicalView mViewA;
	private static GraphicalView mViewB;

	private static Thread mThread;
	private View view;

	private Handler handler;


	private final int maxSeriesValues = 20;


	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		LayoutInflater lf = getActivity().getLayoutInflater();  
		view =  lf.inflate(R.layout.fragment_chart, container, false);
		handler = new MHandler();
		
		int[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW};


		view.findViewById(R.id.checkBoxa1).setOnClickListener(this);
		view.findViewById(R.id.checkBoxa2).setOnClickListener(this);
		view.findViewById(R.id.checkBoxa3).setOnClickListener(this);
		view.findViewById(R.id.checkBoxa4).setOnClickListener(this);
		view.findViewById(R.id.checkBoxb1).setOnClickListener(this);
		view.findViewById(R.id.checkBoxb2).setOnClickListener(this);
		view.findViewById(R.id.checkBoxb3).setOnClickListener(this);
		view.findViewById(R.id.checkBoxb4).setOnClickListener(this);

		timeSeriesa1 = new TimeSeries("Port 1");
		timeSeriesa2 = new TimeSeries("Port 2");
		timeSeriesa3 = new TimeSeries("Port 3");
		timeSeriesa4 = new TimeSeries("Port 4");
		timeSeriesb1 = new TimeSeries("Port 1");
		timeSeriesb2 = new TimeSeries("Port 2");
		timeSeriesb3 = new TimeSeries("Port 3");
		timeSeriesb4 = new TimeSeries("Port 4");

		rendererSeriesa1 = new XYSeriesRenderer();
		rendererSeriesa2 = new XYSeriesRenderer();
		rendererSeriesa3 = new XYSeriesRenderer();
		rendererSeriesa4 = new XYSeriesRenderer();
		rendererSeriesb1 = new XYSeriesRenderer();
		rendererSeriesb2 = new XYSeriesRenderer();
		rendererSeriesb3 = new XYSeriesRenderer();
		rendererSeriesb4 = new XYSeriesRenderer();

		seriesRendererList = new ArrayList<XYSeriesRenderer>();

		seriesRendererList.add(rendererSeriesa1);
		seriesRendererList.add(rendererSeriesa2);
		seriesRendererList.add(rendererSeriesa3);
		seriesRendererList.add(rendererSeriesa4);
		seriesRendererList.add(rendererSeriesb1);
		seriesRendererList.add(rendererSeriesb2);
		seriesRendererList.add(rendererSeriesb3);
		seriesRendererList.add(rendererSeriesb4);

		seriesList = new ArrayList<TimeSeries>();

		seriesList.add(timeSeriesa1);
		seriesList.add(timeSeriesa2);
		seriesList.add(timeSeriesa3);
		seriesList.add(timeSeriesa4);
		seriesList.add(timeSeriesb1);
		seriesList.add(timeSeriesb2);
		seriesList.add(timeSeriesb3);
		seriesList.add(timeSeriesb4);


		rendererA = new XYMultipleSeriesRenderer();
		rendererA.setAxesColor(Color.BLACK);
		rendererA.setAxisTitleTextSize(16);
		rendererA.setChartTitle("Port Current Voltage");
		rendererA.setChartTitleTextSize(15);
		rendererA.setFitLegend(true);
		rendererA.setGridColor(Color.BLACK);
		rendererA.setPanEnabled(true, true);
		rendererA.setPointSize(5);
		rendererA.setXTitle("Time");
		rendererA.setYTitle("Voltage");
		rendererA.setMargins(new int []{20, 30, 15, 10});
		rendererA.setZoomButtonsVisible(true);
		rendererA.setBarSpacing(10);
		rendererA.setShowGrid(true);
		rendererA.setMarginsColor(Color.WHITE);
		rendererA.setXLabelsColor(Color.BLACK);
		rendererA.setYLabelsColor(0, Color.BLACK);

		rendererB = new XYMultipleSeriesRenderer();
		rendererB.setAxesColor(Color.BLACK);
		rendererB.setAxisTitleTextSize(16);
		rendererB.setChartTitle("Port Current Chart");
		rendererB.setChartTitleTextSize(15);
		rendererB.setFitLegend(true);
		rendererB.setGridColor(Color.BLACK);
		rendererB.setPanEnabled(true, true);
		rendererB.setPointSize(5);
		rendererB.setXTitle("Time");
		rendererB.setYTitle("Current");
		rendererB.setMargins(new int []{20, 30, 15, 10});
		rendererB.setZoomButtonsVisible(true);
		rendererB.setBarSpacing(10);
		rendererB.setShowGrid(true);
		rendererB.setMarginsColor(Color.WHITE);
		rendererB.setXLabelsColor(Color.BLACK);
		rendererB.setYLabelsColor(0, Color.BLACK);

		datasetA = new XYMultipleSeriesDataset();
		datasetB = new XYMultipleSeriesDataset();

		int col = 0;



		for (XYSeriesRenderer sr : seriesRendererList) {
			sr.setColor(colors[col]);
			sr.setFillPoints(true);
			sr.setPointStyle(PointStyle.CIRCLE);
			col = (col +  1) % 4;
		}		

		/*		mThread = new Thread(){
			public void run(){
				while(true){
					try {
						Thread.sleep(2000L);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					for (int i = 1; i < seriesList.size()+1; i++) {
						addValueToSerie(i, new Date(), random.nextDouble()*10.0);
						i++;
					}

					mViewA.repaint();
					mViewB.repaint();
				}
			}
		};
		mThread.start();
		 */
		CheckSeriesSize checker = new CheckSeriesSize();

		checker.start();

		return view;	   
	}

	public void startChart(){

		mViewA = ChartFactory.getTimeChartView(getActivity(), datasetA, rendererA, "Test");
		mViewA.refreshDrawableState();
		mViewA.repaint();
		FrameLayout frameLayoutA = (FrameLayout)view.findViewById(R.id.chartFrame1);
		frameLayoutA.addView(mViewA);

		mViewB = ChartFactory.getTimeChartView(getActivity(), datasetB, rendererB, "Test");
		mViewB.refreshDrawableState();
		mViewB.repaint();
		FrameLayout frameLayoutB = (FrameLayout)view.findViewById(R.id.chartFrame2);
		frameLayoutB.addView(mViewB);

	}

	/* (non-Javadoc)
	 * @see android.support.v4.app.Fragment#onAttach(android.app.Activity)
	 */
	@Override
	public void onAttach(Activity activity) { 
		// TODO Auto-generated method stub
		super.onAttach(activity);
	}

	/* (non-Javadoc)
	 * @see android.support.v4.app.Fragment#onDetach()
	 */
	@Override
	public void onDetach() {
		// TODO Auto-generated method stub
		super.onDetach();
	}

	private void addSeriesToView(TimeSeries t, XYSeriesRenderer r, String v){
		if(v.equals("a")){
			datasetA.addSeries(t);
			rendererA.addSeriesRenderer(r);
			mViewA.refreshDrawableState();
			mViewA.repaint();	
		}else{
			datasetB.addSeries(t);
			rendererB.addSeriesRenderer(r);
			mViewB.refreshDrawableState();
			mViewB.repaint();
		}
	}

	private void removeSeriesFromView(TimeSeries t, XYSeriesRenderer r, String v){
		if(v.equals("a")){
			datasetA.removeSeries(t);
			rendererA.removeSeriesRenderer(r);
			mViewA.refreshDrawableState();
			mViewA.repaint();
		}else{
			datasetB.removeSeries(t);
			rendererB.removeSeriesRenderer(r);
			mViewB.refreshDrawableState();
			mViewB.repaint();
		}
	}

	/* (non-Javadoc)
	 * @see android.view.View.OnClickListener#onClick(android.view.View)
	 */
	@Override
	public void onClick(View view) {
		boolean checked = ((CheckBox) view).isChecked();

		switch(view.getId()) {
		case R.id.checkBoxa1:
			if (checked){
				addSeriesToView(timeSeriesa1, rendererSeriesa1, "a");
			}else{
				removeSeriesFromView(timeSeriesa1, rendererSeriesa1, "a");
			}
			break;
		case R.id.checkBoxa2:
			if (checked){
				addSeriesToView(timeSeriesa2, rendererSeriesa2, "a");
			}else{
				removeSeriesFromView(timeSeriesa2, rendererSeriesa2, "a");
			}
			break;
		case R.id.checkBoxa3:
			if (checked){
				addSeriesToView(timeSeriesa3, rendererSeriesa3, "a");
			}else{
				removeSeriesFromView(timeSeriesa3, rendererSeriesa3, "a");
			}
			break;
		case R.id.checkBoxa4:
			if (checked){
				addSeriesToView(timeSeriesa4, rendererSeriesa4, "a");
			}else{
				removeSeriesFromView(timeSeriesa4, rendererSeriesa4, "a");
			}
			break;
		case R.id.checkBoxb1:
			if (checked){
				addSeriesToView(timeSeriesb1, rendererSeriesb1, "b");
			}else{
				removeSeriesFromView(timeSeriesb1, rendererSeriesb1, "b");
			}
			break;
		case R.id.checkBoxb2:
			if (checked){
				addSeriesToView(timeSeriesb2, rendererSeriesb2, "b");
			}else{
				removeSeriesFromView(timeSeriesb2, rendererSeriesb2, "b");
			}
			break;
		case R.id.checkBoxb3:
			if (checked){
				addSeriesToView(timeSeriesb3, rendererSeriesb3, "b");
			}else{
				removeSeriesFromView(timeSeriesb3, rendererSeriesb3, "b");
			}
			break;
		case R.id.checkBoxb4:
			if (checked){
				addSeriesToView(timeSeriesb4, rendererSeriesb4, "b");
			}else{
				removeSeriesFromView(timeSeriesb4, rendererSeriesb4, "b");
			}
			break;
		default:
			break;
		}

	}

	public void addValueToSerie(int port, Date d, double v){
		switch (port) {
		case 1:
			timeSeriesa1.add(d, v);
			break;
		case 2:
			timeSeriesa2.add(d, v);
			break;
		case 3:
			timeSeriesa3.add(d, v);
			break;
		case 4:
			timeSeriesa4.add(d, v);
			break;
		case 5:
			timeSeriesb1.add(d, v);
			break;
		case 6:
			timeSeriesb2.add(d, v);
			break;
		case 7:
			timeSeriesb3.add(d, v);
			break;
		case 8:
			timeSeriesb4.add(d, v);
			break;
		default:
			break;
		}
		repaintViews();
	}

	public void setValuesToSerie(int port, Map<Date, Double> m){
		switch (port) {
		case 1:
			setTimeSeries(timeSeriesa1, m);
			break;
		case 2:
			setTimeSeries(timeSeriesa2, m);
			break;
		case 3:
			setTimeSeries(timeSeriesa3, m);
			break;
		case 4:
			setTimeSeries(timeSeriesa4, m);
			break;
		case 5:
			setTimeSeries(timeSeriesb1, m);
			break;
		case 6:
			setTimeSeries(timeSeriesb2, m);
			break;
		case 7:
			setTimeSeries(timeSeriesb3, m);
			break;
		case 8:
			setTimeSeries(timeSeriesb4, m);
			break;
		default:
			break;
		}

		repaintViews();
	}

	private void setTimeSeries(TimeSeries t, Map<Date, Double> m){
		for (int i = 0; i < t.getItemCount(); i++){
			t.remove(0);
		}
		for (Map.Entry<Date, Double> entry : m.entrySet()) {
			t.add(entry.getKey(), entry.getValue());
		}
		repaintViews();
	}

	private void repaintViews(){
		mViewA.repaint();
		mViewB.repaint();

	}

	private class CheckSeriesSize extends Thread{



		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			for (TimeSeries ts : seriesList) {
				while(ts.getItemCount() > maxSeriesValues){
					//ts.remove(ts.getIndexForKey(ts.getMinX()));
					ts.remove(0);
				}
			}
			repaintViews();

		}

	}

	private class MHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			Bundle bundle = msg.getData();
			
			if(bundle.containsKey("ts")){
				Date date = new Date(bundle.getLong("ts"));

				for(int i = 1; i<9; i++){
					if(bundle.containsKey(i + "")){
						//if(!bundle.getString(i + "").equals("")){
							Double value = Double.parseDouble(bundle.getString(i + ""));
							addValueToSerie(i, date, value);
						//}
					}
				}
			}
		}
	}
	
	public void addDatas(Bundle b){
		notifyMessage(b);
	}
	
	private void notifyMessage(Bundle b){
		Message msg = handler.obtainMessage();
		msg.setData(b);
		handler.sendMessage(msg);
	}
	

}
